/*
* @desc:  公共服务层对象
* @company:中海创科技
* @Author: lfzxs@qq.com
* @Date:   2022/5/10 9:28
 */

package libService

import (
	"reflect"
	"strings"

	"gitee.com/g_boot/chkboot-common/library/libUtils"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/tidwall/gjson"
)

type Condition int 
//条件枚举
const (
	//等于
	Condition_EQ Condition = 0
	//不等于
	Condition_NE Condition = 1
	//大于
	Condition_GT Condition = 2
	//大于等于
	Condition_GE Condition = 3
	//小于
	Condition_LT Condition = 4
	//小于等于
	Condition_LE Condition = 5
    //like '%值%'
	Condition_LIKE Condition = 20
    //like '%值'
	Condition_LIKE_LEFT Condition = 21
	//like '值%'
	Condition_LIKE_RIGHT Condition = 22
	//in
	Condition_IN Condition = 30

	//分页页码字段名
	Page_Filed_PgNum_NAME = "PageNum"
	//分页每页条数字段名
	Page_Filed_SIZE_NAME = "PageSize"
)

var ConditionStrToEnum map[string]Condition = map[string]Condition{
	"eq":Condition_EQ,
	"ne":Condition_NE,
	"gt":Condition_GT,
	"ge":Condition_GE,
	"lt":Condition_LT,
	"le":Condition_LE,
	"like":Condition_LIKE,
	"like_left":Condition_LIKE_LEFT,
	"like_right":Condition_LIKE_RIGHT,
	"in":Condition_IN,
}


//查询项
type QueryItem struct {
	//字段名
	Field string
	//条件
	Cond  Condition
	//值
	Value interface{}
}

//条件构造器
type QueryWrapper struct {
	Quserys []*QueryItem
}

//排序对象
type OrderItem struct {
	Column string
	Asc    bool
}

//分页查询对象
type PageQuery struct {
	// 每页记录数
	Size uint32
	// 当前页码
	Current uint32
	// 排序
	Orders []*OrderItem
}

//分页查询输入对象
type PageInp struct {
	PageQuery
	QueryWrapper
}

type PageModel struct {
	// 当前页码
	Current int	`json:"current" dc:"当前页码"`
	// 记录数
	Size int  `json:"size" dc:"每页记录数"`
	// 总记录数
	Total int `json:"total" dc:"总记录数"`
	// 数据记录
	List interface{}
}


type DataWrapper struct {
	Model map[string]interface{}
}

//更新
type EditWrapper struct {
	DataWrapper
	QueryWrapper
}

type AddWrapper struct {
	DataWrapper
}


var ServiceUtil = serviceUtil{DefPageSize:20,DefCurrent:0}

//service公共函数
type  serviceUtil struct{
	// 默认页面条数
	DefPageSize uint32 
	// 默认页码
	DefCurrent  uint32
}


// 构建查询项
func BuildQueryItem(field string,cond Condition,value any)(result *QueryItem){
	result = &QueryItem{
		Field: field,
		Cond: cond,
		Value: value,
	}

	return result
}

// 追加查询条件
func (quw *QueryWrapper) AppendQueryItem(field string,cond Condition,value any)(result *QueryWrapper){
	item := &QueryItem{
		Field: field,
		Cond: cond,
		Value: value,
	}
	quw.Quserys = append(quw.Quserys, item)

	return quw
}


func (service *serviceUtil) MakeWhereAndOrder(m *gdb.Model,pageQuery *PageInp)(*gdb.Model){
	result := m
	result = service.MakeWhere(result, &pageQuery.QueryWrapper)
	result =  service.MakeOrder(result, pageQuery)
	return result
}

// 构建分页排序条件
func (service *serviceUtil) MakeOrder(m *gdb.Model,pageQuery *PageInp)(*gdb.Model){


	var(
		pagesize uint32 = pageQuery.Size
		current uint32 = pageQuery.Current 

	)
	// 设置每页记录数
	if(0>=pagesize){pagesize = service.DefPageSize}

	// 
	if(0>=current){current=service.DefCurrent}


	oper := m.Page(int(current), int(pagesize))

	for i := 0; i < len(pageQuery.Orders); i++ {
		orderitem := pageQuery.Orders[i]

		if orderitem.Asc {
			oper = oper.OrderAsc(orderitem.Column)
		} else {
			oper = oper.OrderDesc(orderitem.Column)
		}

	}
	return oper
}

// 构建分页查询条件
func (service *serviceUtil) MakeWhere(m *gdb.Model,query *QueryWrapper)(*gdb.Model){
	oper := m 
	for _, v := range query.Quserys {
		
		switch v.Cond{
		case Condition_EQ:
			oper = oper.Where(v.Field,v.Value)
		case Condition_NE:
			oper = oper.WhereNot(v.Field,v.Value)
		case Condition_GT:
			oper = oper.WhereGT(v.Field,v.Value)
		case Condition_GE:
			oper = oper.WhereGTE(v.Field,v.Value)
		case Condition_LT:
			oper = oper.WhereLT(v.Field,v.Value)
		case Condition_LE:
			oper = oper.WhereLTE(v.Field,v.Value)


		case Condition_LIKE:
			oper = oper.WhereLike(v.Field,"%"+ libUtils.InterfaceToString(v.Value)+"%")
		case Condition_LIKE_LEFT:
			oper = oper.WhereLike(v.Field,"%"+ libUtils.InterfaceToString(v.Value))
		case Condition_LIKE_RIGHT:
			oper = oper.WhereLike(v.Field, libUtils.InterfaceToString(v.Value)+"%")

		case Condition_IN:
			oper = oper.WhereIn(v.Field,strings.Split(libUtils.InterfaceToString(v.Value), ","))
		
		}
	}

	return oper
}

func (service *serviceUtil) MakeQueryItem(field string,cond Condition,value string)(result QueryItem){

	result.Field = field
	result.Cond = cond
	result.Value = value

	return 

}

//构造通用分页条件
func (service *serviceUtil) MakePageWrapper(model any )(result PageQuery){

	pagNum,ok := libUtils.GetStructItemValue(model,Page_Filed_PgNum_NAME)
	if(ok){
		result.Current = uint32(pagNum.(int))
	}
	pagSize,ok := libUtils.GetStructItemValue(model,Page_Filed_SIZE_NAME)

	if(ok){
		result.Size = uint32(pagSize.(int))
	}

	return
}

//构造通用查询条件
func (service *serviceUtil) MakeQueryWrapper(model any,flag ...string)(result QueryWrapper){	
	var(
		quserys []*QueryItem	
	)

	db_commentCall := func (field reflect.StructField,value any){
		dbjson := field.Tag.Get("db") 
		if(len(dbjson)>0){
			dbjson = strings.ReplaceAll(dbjson,"'","\"")
			
			if(nil != value && len(libUtils.InterfaceToString(value))>0){

				// 是否存在过滤标识
				if(len(flag)>0){
					tag_flag := gjson.Get(dbjson,"flag").String()

					if(!strings.EqualFold(flag[0], tag_flag)){
						return
					}
					
				}

				var item QueryItem
				//查询字段名
				item.Field = gjson.Get(dbjson,"field").String()

				//查询条件
				condStr := gjson.Get(dbjson,"search").String()

				

				cond,ok := ConditionStrToEnum[condStr]
				if(ok){
					item.Cond = cond
				}else{
					item.Cond = Condition_EQ
				}

				
				item.Value = value


				quserys = append(quserys, &item)
			}
		}
	}

	libUtils.ForEachStruct(model,db_commentCall)
	result.Quserys = quserys
	return
}

// 构建查询和排序条件
func (service *serviceUtil) MakeQueryAndOrderWrapper(model any , input *PageInp){
	input.QueryWrapper = service.MakeQueryWrapper(model)
	input.PageQuery = service.MakePageWrapper(model)
}

// 构建删除条件
func (service *serviceUtil) MakeDeleteWrapper(model any)(result QueryWrapper){
	return service.MakeQueryWrapper(model)
}

// 构建修改条件
func (service *serviceUtil) MakeEditWrapper(model any)(*EditWrapper){

	result := EditWrapper{}

	//result.Model = 

	result.QueryWrapper = service.MakeQueryWrapper(model,"updateWhere")
	
	result.DataWrapper = service.MakeDataWrapper(model)
	return &result 
}


// 构建实体与数据对应关系
func (service *serviceUtil) MakeDataWrapper(model any)(DataWrapper){
	dataModel := DataWrapper{}
	dataModel.Model = map[string]interface{}{}

	//"db":{"field":"name","def":"1","def_fun":"snowflakeId" }
	db_commentCall := func (field reflect.StructField,value any){
		dbjson := field.Tag.Get("db") 
		if(len(dbjson)>0){
			dbjson = strings.ReplaceAll(dbjson,"'","\"")
			fieldstr := gjson.Get(dbjson,"field").String()

			if(value != nil && (!reflect.ValueOf(value).IsZero())){
				dataModel.Model[fieldstr] = value
				return 
			}

			// 默认值
			defstr := gjson.Get(dbjson,"def").String()
			if(len(defstr)>0) {
				dataModel.Model[fieldstr]=defstr
				return 
			}

			// 默认值函数
			defstr = gjson.Get(dbjson,"def_fun").String()
			if(len(defstr)>0) {
				defFun := FunMap[defstr]
				if(nil != defFun){dataModel.Model[fieldstr]=defFun() } 
				return
			}
		}
	}

	libUtils.ForEachStruct(model,db_commentCall)
	return dataModel
}

// 构建新增对象
func (service *serviceUtil) MakeAddWrapper(model any)(*AddWrapper){
	var(
		result AddWrapper 
	)

	result.DataWrapper = service.MakeDataWrapper(model)

	return &result 
}


